package model

import (
	"fmt"
	"os/exec"
	"time"
)

// Room 战斗房间
type Room struct {
	RoomId         int     // 房间id
	BattleInstance *Battle // 战斗实例
	CreatedAt      time.Time
	Status         string // "waiting", "battling", "finished"
}

// Battle 战斗实例
type Battle struct {
	BattleId     string                     // 战斗实例唯一id
	RoomId       int                        // 战斗房间id
	PlayerId1    int                        // 玩家1id
	PlayerId2    int                        // 玩家2id
	FightHeroes  map[int]map[int]*FightHero // 对战双方的英雄及其位置
	CurrentRound int                        // 当前回合数
	ActionQueue  []*FightHero               // 当前回合行动顺序
	BattleLog    []BattleLogEntry           // 战斗日志
	StartTime    time.Time                  // 战斗开始时间
	EndTime      time.Time                  // 战斗结束时间
	Status       string                     // "preparing", "in_progress", "finished"
	Winner       int                        // 获胜方ID，0表示未决出
	MaxRounds    int                        // 最大回合数
}

// BattleLogEntry 战斗日志条目
type BattleLogEntry struct {
	Round      int       // 回合数
	Timestamp  time.Time // 时间戳
	ActorId    int       // 行动者ID
	TargetIds  []int     // 目标ID列表
	ActionType string    // 行动类型：attack, skill, buff, debuff, death
	SkillId    int       // 技能ID，如果是技能行动
	Damage     int       // 造成的伤害，如果有
	Healing    int       // 治疗量，如果有
	Message    string    // 日志消息
}

// FightHero 战斗中的英雄
type FightHero struct {
	HeroId          int         // 英雄id
	HeroName        string      // 英雄名称
	Job             int         // 英雄职业
	JobName         string      // 职业名称
	MaxHp           int         // 最大血量
	CurrentHp       int         // 当前血量
	Attack          int         // 攻击
	Defense         int         // 防御
	Speed           int         // 速度
	CritRate        float64     // 暴击率
	CritDamage      float64     // 暴击伤害
	MagicPower      int         // 魔法攻击力
	HealEffect      float64     // 治疗效果
	DamageReduction float64     // 伤害减免
	Shield          int         // 护盾值
	PlayerId        int         // 玩家id
	Position        int         // 英雄位置
	Buffs           []Effect    // 英雄身上的buff
	Debuffs         []Effect    // 英雄身上的debuff
	SkillCDs        map[int]int // 英雄技能cd - 剩余cd
	Skills          []int       // 英雄拥有的技能ID列表
	IsAlive         bool        // 英雄是否存活
	ActionTaken     bool        // 当前回合是否已行动
}

// Effect 效果
type Effect struct {
	ID          int             // 效果唯一ID
	Type        SkillEffectType // 效果类型
	Value       int             // 效果数值
	Duration    int             // 持续剩余回合
	SourceId    int             // 效果来源英雄ID
	AppliedTime time.Time       // 效果应用时间
	Description string          // 效果描述
}

// BattleResult 战斗结果
type BattleResult struct {
	BattleId     string           // 战斗ID
	Winner       int              // 获胜方ID
	Duration     int              // 战斗持续回合数
	TotalTime    time.Duration    // 战斗总时长
	MVP          int              // MVP英雄ID
	DamageStats  map[int]int      // 各英雄造成的伤害统计
	HealingStats map[int]int      // 各英雄治疗量统计
	Survivors    []*FightHero     // 存活的英雄
	BattleLog    []BattleLogEntry // 战斗日志
}

// 创建新的战斗实例
func NewBattle(roomId, player1Id, player2Id int) *Battle {
	return &Battle{
		BattleId:     GenerateUniqueId(),
		RoomId:       roomId,
		PlayerId1:    player1Id,
		PlayerId2:    player2Id,
		FightHeroes:  make(map[int]map[int]*FightHero),
		CurrentRound: 0,
		ActionQueue:  make([]*FightHero, 0),
		BattleLog:    make([]BattleLogEntry, 0),
		StartTime:    time.Now(),
		Status:       "preparing",
		Winner:       0,
		MaxRounds:    15, // 默认最大回合数
	}
}

// 添加英雄到战斗
func (b *Battle) AddHero(hero *FightHero, position int) error {
	// 初始化玩家的位置映射，如果不存在
	if _, exists := b.FightHeroes[hero.PlayerId]; !exists {
		b.FightHeroes[hero.PlayerId] = make(map[int]*FightHero)
	}

	// 检查位置是否已被占用
	if _, occupied := b.FightHeroes[hero.PlayerId][position]; occupied {
		return fmt.Errorf("position already occupied")
	}

	// 设置英雄位置
	hero.Position = position

	// 添加英雄到指定位置
	b.FightHeroes[hero.PlayerId][position] = hero

	return nil
}

// 获取指定位置的英雄
func (b *Battle) GetHeroAtPosition(playerId int, position int) *FightHero {
	if playerHeroes, exists := b.FightHeroes[playerId]; exists {
		if hero, exists := playerHeroes[position]; exists {
			return hero
		}
	}
	return nil
}

// 获取前排英雄
func (b *Battle) GetFrontRowHeroes(playerId int) []*FightHero {
	result := make([]*FightHero, 0)
	if playerHeroes, exists := b.FightHeroes[playerId]; exists {
		for pos, hero := range playerHeroes {
			if pos <= 3 && hero.IsAlive { // 前排
				result = append(result, hero)
			}
		}
	}

	// 如果没有前排英雄，尝试获取后排英雄
	if len(result) == 0 {
		result = b.GetBackRowHeroes(playerId)
	}
	return result
}

// 获取后排英雄
func (b *Battle) GetBackRowHeroes(playerId int) []*FightHero {
	result := make([]*FightHero, 0)
	if playerHeroes, exists := b.FightHeroes[playerId]; exists {
		for pos, hero := range playerHeroes {
			if pos > 3 && hero.IsAlive { // 后排
				result = append(result, hero)
			}
		}
	}
	// 如果没有后排英雄，尝试获取前排英雄
	if len(result) == 0 {
		result = b.GetFrontRowHeroes(playerId)
	}
	return result
}

// 获取所有存活英雄
func (b *Battle) GetAllAliveHeroes(playerId int) []*FightHero {
	result := make([]*FightHero, 0)
	if playerHeroes, exists := b.FightHeroes[playerId]; exists {
		for _, hero := range playerHeroes {
			if hero.IsAlive {
				result = append(result, hero)
			}
		}
	}
	return result
}

// 记录战斗日志
func (b *Battle) LogAction(entry BattleLogEntry) {
	entry.Round = b.CurrentRound
	entry.Timestamp = time.Now()
	b.BattleLog = append(b.BattleLog, entry)
}

// 生成战斗结果
func (b *Battle) GenerateResult() *BattleResult {
	b.EndTime = time.Now()

	// 计算伤害和治疗统计
	damageStats := make(map[int]int)
	healingStats := make(map[int]int)

	for _, entry := range b.BattleLog {
		if entry.ActionType == "attack" || entry.ActionType == "skill" {
			damageStats[entry.ActorId] += entry.Damage
		}
		if entry.ActionType == "heal" {
			healingStats[entry.ActorId] += entry.Healing
		}
	}

	// 收集存活英雄
	survivors := make([]*FightHero, 0)
	for _, playerHeroes := range b.FightHeroes {
		for _, hero := range playerHeroes {
			if hero.IsAlive {
				survivors = append(survivors, hero)
			}
		}
	}

	return &BattleResult{
		BattleId:     b.BattleId,
		Winner:       b.Winner,
		Duration:     b.CurrentRound,
		TotalTime:    b.EndTime.Sub(b.StartTime),
		DamageStats:  damageStats,
		HealingStats: healingStats,
		Survivors:    survivors,
		BattleLog:    b.BattleLog,
	}
}

func GenerateUniqueId() string {
	out, err := exec.Command("uuidgen").Output()
	if err != nil {
		panic(err)
	}
	return string(out)
}
